<?php

namespace app\common\logic;

use app\admin\logic\system\Config as SystemConfig;
use app\common\library\Queue;
use app\common\model\Attach as AttachModel;
use eduline\upload\Stock;
use eduline\upload\utils\Util;
use getID3;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Config;
use think\facade\Filesystem;
use think\facade\Request;
use think\File;
use think\Model;

/**
 * 附件管理
 */
class Attach extends AttachModel
{

    /**
     * 添加附件
     *
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-13
     */
    public function saveAttach(File $file, array $filedata = [], ?bool $isTemp = false)
    {
        // 储存当前机构
        $filedata['mhm_id'] = request()->mhm_id;
        if ($isTemp) {
            // 临时文件只存在本地
            $upload              = ['stock' => 'local'];
            $filedata['is_temp'] = 1;
        } else {
            $upload = SystemConfig::get('system.package.upload', ['stock' => 'local'], request()->mhm_id);
        }
        $data = [
            'bucket'    => $this->getDiskName(),
            'stock'     => 'local', // 默认首先都储存到本地,后期同步到云端,该值自动更新
            'to_stock'  => $this->getUploadToStock($file->getExtension(), $upload['stock']), // 当前配置需要同步到储存云端,如果为local,将不会触发同步操作
            'savename'  => $file->getFilename(),
            'savepath'  => $filedata['savepath'] ?? $this->getSavepath($file->getPath()),
            'filename'  => $filedata['filename'] ?? $file->getFilename(),
            'filehash'  => $filedata['filehash'] ?? $file->hash(),
            'filemd5'   => $filedata['filemd5'] ?? $file->hash('md5'),
            'mimetype'  => strtolower($file->getMime()),
            'extension' => $file->getExtension(),
            'filesize'  => $file->getSize(),
            'filedata'  => $filedata,
            'from'      => Request::header('E-DEVICE-TYPE', 'public'),
        ];

        if ($this->save($data)) {
            // 添加任务: 不是本地储存时,投递任务
            if ($upload['stock'] != 'local') {
                // 延迟5秒执行
                Queue::push('UploadYunSync', ['attach_id' => $this->getAttr('id')], 5);
            } else if ($this->isAudioOrVideo($this)) {
                // 获取时长
                $getID3   = new getID3();
                $analyze  = $getID3->analyze($file->getRealPath());
                $duration = floor($analyze['playtime_seconds']);

                AttachModel::update(['duration' => $duration], ['stock' => 'local', 'id' => $this->getAttr('id')]);
            }

            try {
                return $this->find($this->getAttr('id'));
            } catch (DataNotFoundException|ModelNotFoundException|DbException $e) {
            }
        }

        return false;
    }

    /**
     * 获取上传储存的位置: 检测并过滤上传到云端的文件
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/1/26
     *
     * @param $extension
     * @param $stock
     * @return string
     */
    protected function getUploadToStock($extension, $stock)
    {
        $exts = Config::get('filesystem.cloud_filter_extension', '');
        $exts = explode(',', $exts);
        if (in_array($extension, $exts)) {
            return 'local';
        }

        return $stock;
    }

    /**
     * 获取保存的目录
     *
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-13
     *
     * @param    [type]                         $filepath [description]
     * @return string [type]                                   [description]
     */
    protected function getSavepath($filepath)
    {
        return $this->getUploadDir() . '/' . str_replace($this->getUploadPath(), '', $filepath);
    }

    /**
     * 获取文件的上传保存磁盘根路径
     *
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-13
     *
     * @return string [type]                               [description]
     */
    public function getDiskPath(): string
    {
        return Filesystem::getDiskConfig($this->getDiskName(), 'root');
    }

    /**
     * 上传保存目录名称
     *
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-13
     *
     * @return mixed [type]                         [description]
     */
    public function getUploadDir()
    {
        return Stock::getStockConfig('local')['upload_dir'];
    }

    /**
     * 当前储存磁盘名称
     *
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-13
     *
     * @return mixed [type]                         [description]
     */
    public function getDiskName()
    {
        return Stock::getStockConfig('local')['bucket'];
    }

    /**
     * 获取上传保存路径
     *
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-13
     *
     * @param string $path [description]
     * @return string [type]                               [description]
     */
    public function getUploadPath($path = ''): string
    {
        return $this->getDiskPath() . '/' . $this->getUploadDir() . '/' . $path;
    }

    /**
     * 根据文件ID获取附件
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/3/30
     *
     * @param int $id
     * @return array|Model
     */
    public function getAttachById(int $id)
    {
        return $this->where('id', $id)->findOrFail();
    }

    /**
     * 附件类型是否是音视频
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-06-16
     *
     * @param AttachModel $attach [description]
     * @return boolean             [description]
     */
    public function isAudioOrVideo(AttachModel $attach)
    {
        return Util::isAudio($attach['mimetype'], $attach['extension']) || Util::isVideo($attach['mimetype'], $attach['extension']);
    }

    /**
     * 获取文件名称
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/7/20
     *
     * @param int $attachId
     * @return mixed|string
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getAttachTitle($attachId)
    {
        $attach = $this->where('id', $attachId)->find();
        if ($attach) {
            return $attach->getAttr('filename');
        }

        return '未知';
    }
}
